/***
 *  C++ 多态
 *      动态多态
 *          虚函数/纯虚函数
 *          抽象类/接口类
 */

#include <iostream>
#include <cmath>

 // 抽象类
 class Organism{
public:
    virtual void growup() = 0;// 纯虚函数
    virtual void eating(){
        std::cout << "eating everything" << std::endl;
    };
 };

// 基类 Animal 还是抽象类，无法实例化对象
class Animal : public Organism{
public:
    // 虚函数 speak()
    virtual void speak() {
        std::cout << "动物发出声音" << std::endl;
    }
};

// 派生类 Cat
class Cat : public Animal {
public:
    void growup(){
        std::cout<< "猫越长越大" << std::endl;
    }
    // 重写 speak() 函数
    void speak() override {
        std::cout << "喵~" << std::endl;
    }
};

// 派生类 Dog
class Dog : public Animal {
public:
    void growup(){
        std::cout<< "狗越长越大" << std::endl;
    }
    // 重写 speak() 函数
    void speak() override {
        std::cout << "汪！" << std::endl;
    }
};

// 抽象类 Shape；接口类
class Shape {
public:
    // 纯虚函数 area()
    virtual double area() = 0;
};
    
// 派生类 Circle
class Circle : public Shape {
private:
    double radius;
public:
    Circle(double r) : radius(r) {}
    // 重写 area() 函数
    double area() override {
        return M_PI * radius * radius;
    }
};
    
// 派生类 Rectangle
class Rectangle : public Shape {
private:
    double width;
    double height;
public:
    Rectangle(double w, double h) : width(w), height(h) {}
    // 重写 area() 函数
    double area() override {
        return width * height;
    }
};
    

int main() {
    // 创建 Cat 和 Dog 对象
    Cat cat;
    Dog dog;

    // 使用基类指针指向派生类对象
    Animal* animal1 = &cat;
    Animal* animal2 = &dog;

    // 调用虚函数
    animal1->speak(); // 输出：喵~
    animal2->speak(); // 输出：汪！
    animal1->growup(); // 输出：喵~
    animal2->growup(); // 输出：汪！

    animal1->Animal::speak(); // 输出：动物发出声音

    ///////////////////////////////////////////////////////

    // 创建 Circle 和 Rectangle 对象
    Circle circle(5.0);
    Rectangle rectangle(3.0, 4.0);

    // 使用基类指针指向派生类对象
    Shape* shape1 = &circle;
    Shape* shape2 = &rectangle;

    // 调用纯虚函数
    std::cout << "圆的面积：" << shape1->area() << std::endl;
    std::cout << "矩形的面积：" << shape2->area() << std::endl;
    return 0;
}